/**
 * Copyright 2011 Honeywell Federal Manufacturing & Technologies, LLC. This material was produced under U.S. Government
 * contract DE-ACO4-01AL66850, Honeywell Federal Manufacturing & Technologies, LLC, (FM&T) with the U. S. Department of
 * Energy for the operation of the Kansas City Plant . The U.S. Government has rights to use, reproduce, and distribute
 * this software.  NEITHER THE GOVERNMENT NOR Honeywell Federal Manufacturing & Technologies, LLC, MAKES ANY WARRANTY,
 * EXPRESS OR IMPLIED, OR ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified to produce
 * derivative works, such modified software should be clearly marked, so as not to confuse it with the version available
 * from FM&T.
 *
 * Additionally, this program is free software; you can redistribute it and/or modify it under the terms of the GNU
 * General Public License Version 3 published by the Free Software Foundation. Accordingly, this program is distributed in
 * the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this library.
 * If not, see http://www.gnu.org/licenses/.
 */
package org.braintrain.tapestry.services;

import com.kcp.ko.fmtnmlib.csv.AbstractIteratableDataSource;
import com.kcp.ko.fmtnmlib.csv.CSVDataSource;
import com.kcp.ko.fmtnmlib.csv.CSVWriter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.PageRedirectException;
import org.apache.tapestry.util.ContentType;
import org.apache.tapestry.web.WebResponse;
import org.braintrain.domain.AnswerLog;
import org.braintrain.domain.Module;

import javax.activation.MimetypesFileTypeMap;
import java.io.IOException;
import java.io.OutputStream;
import java.text.DateFormat;
import java.util.Iterator;
import java.util.List;

/**
 * The Tapestry Service for building and hosting the Answer Log CSV.
 * @author John Ericksen
 * @author Robert H. Engelhardt
 *
 */
public class TestAnswerLogCSVService extends BrainTrainEngineServiceAdapter {

    public static final String SERVICE_NAME = "testAnswerLogCSVService";
    public static final String FILE_NAME = "testAnserLog.csv";
    public static final String MODULE_ID = "moduleId";
    
    private MimetypesFileTypeMap mimeTypes = new MimetypesFileTypeMap();
    
    private static final Log log = LogFactory.getLog(TestAnswerLogCSVService.class); // define log
    
    /*
     * (non-Javadoc)
     * @see org.apache.tapestry.engine.IEngineService#getName()
     */
    public String getName() {
        return SERVICE_NAME;
    }
    
    /*
     * (non-Javadoc)
     * @see org.apache.tapestry.engine.IEngineService#service(org.apache.tapestry.IRequestCycle)
     */
    public void service(IRequestCycle cycle) throws IOException {
        	
		if(!getBraintrainVisit().getAuthenticatedUser().hasBasicAccess()) {
			throw new PageRedirectException("NotAuthorized");
		}
		
		log.info( getBraintrainVisit().getAuthenticatedUser().getProfile().getName().toString() + " retrieved file via " + SERVICE_NAME);	// log event
        
        Long moduleId = unsqueezeParameter(cycle, Long.class, MODULE_ID);
        Module module = getHibernateSearchService().getById(Module.class, moduleId);
        List<AnswerLog> answerLog = module.getAnswerLog();

		WebResponse response = cycle.getInfrastructure().getResponse();
		response.setHeader("Content-disposition", "attachment; filename=" + FILE_NAME);
		response.setHeader("Cache-Control", "max-age=0");
		OutputStream out = response.getOutputStream(new ContentType(mimeTypes.getContentType(FILE_NAME)));
		
		CSVDataSource datasource = new AnswerLogCSVDatasource(answerLog.iterator());
		
		CSVWriter.writeCSV(datasource, out);	// render CSV data
		out.flush();

    }

    /**
     * CSV Data source for the answer logs
     * @author Robert H. Engelhardt
     *
     */
    public static class AnswerLogCSVDatasource extends AbstractIteratableDataSource<AnswerLog> {

		private static final long serialVersionUID = 1251118405573297160L;

		/**
    	 * Construct a new AnswerLogCSVDatasource
    	 * @param answerLogIterator the iterator to a collection of answer logs
    	 */
    	public AnswerLogCSVDatasource(final Iterator<AnswerLog> answerLogIterator) {
    		setRecordIterator(answerLogIterator);
    	}
    	
    	/*
    	 * (non-Javadoc)
    	 * @see com.kcp.ko.fmtnmlib.csv.CSVDataSource#columnCount()
    	 */
		public int columnCount() {
			return AnswerLogColumn.values().length;
		}

		/*
		 * (non-Javadoc)
		 * @see com.kcp.ko.fmtnmlib.csv.CSVDataSource#getColumnHeading(int)
		 */
		public String getColumnHeading(int index) {
			return AnswerLogColumn.values()[index].getHeading();
		}

		/*
		 * (non-Javadoc)
		 * @see com.kcp.ko.fmtnmlib.csv.CSVDataSource#getFieldValue(int)
		 */
		public String getFieldValue(int index) {
			return AnswerLogColumn.values()[index].getColumnValue(getCursor());
		}

		/*
		 * (non-Javadoc)
		 * @see com.kcp.ko.fmtnmlib.csv.CSVDataSource#initialize()
		 */
		public void initialize() {
			// nothing to do here
		}    	
    }
    
    /**
     * Column definition for answer log output
     * @author Robert H. Engelhardt
     *
     */
    public static enum AnswerLogColumn {
    	
    	DATE("Date") {
			public String getColumnValue(final AnswerLog cursor) {
				DateFormat format = DateFormat.getDateInstance(DateFormat.SHORT);
				return  cursor.getSubmitDate()!= null ? format.format(cursor.getSubmitDate()) : "";
			}
    	},
    	USER("User") {
			public String getColumnValue(final AnswerLog cursor) {
				
				org.braintrain.domain.User user = cursor.getUser();
				
				if(user== null) {	// this should not occur within the production database, harmless check for dev only
					return "";
				}

				return user.getUserName();
			}
    	},
    	TEST("Test") {
			public String getColumnValue(final AnswerLog cursor) {
				return cursor.getAnswer().getQuestions().getTest().getName();
			}
    	},
    	QUESTION("Question") {
			public String getColumnValue(final AnswerLog cursor) {
				return cursor.getAnswer().getQuestions().getQuestion();
			}
    	},
    	ANSWER("Answer") {
			public String getColumnValue(final AnswerLog cursor) {
				return cursor.getAnswer().getAnswer();
			}
    	},
    	CORRECT("Correct") {
			public String getColumnValue(final AnswerLog cursor) {
				return cursor.isCorrect()? "Yes" : "No";
			}
    	},
    	VERSION("Version") {
			public String getColumnValue(final AnswerLog cursor) {
				return Integer.toString(cursor.getAnswer().getVersion());
			}
    	};    	
    	
    	private final String heading;
    	
    	/**
    	 * Construct a new AnserLogColumn
    	 * @param heading the column heading string
    	 */
    	private AnswerLogColumn(final String heading) {
    		this.heading = heading;
    	}
    	
    	/**
    	 * @return the title of the column
    	 */
    	public String getHeading(){
    		return heading;
    	}

    	/**
    	 * Get the column value based on the row cursor
    	 * @param cursor the current cursor
    	 * @return the column value based on the given cursor
    	 */
    	public abstract String getColumnValue(final AnswerLog cursor);
    	
    }

}
